/**
 * 2017年5月3日
 */
package cn.edu.bjtu.entity.impl.local;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.ReadWriteLock;

import cn.edu.bjtu.classification.ClassificationResult;
import cn.edu.bjtu.classification.LibSVMClassificationResult;
import cn.edu.bjtu.constant.Constant;
import cn.edu.bjtu.entity.LibSVMHolderContext;
import cn.edu.bjtu.entity.impl.BaseLocalContext;
import cn.edu.bjtu.entity.impl.ExecuteContextManager;
import cn.edu.bjtu.entity.impl.api.Word2VecDocTransContext;
import cn.edu.bjtu.settings.ApplicationConfiguration;
import pojo.dto.services.DocumentVectorMessage;


/**
 * @author Alex
 *
 */
public class LibSVMClssifyExecuteContext extends BaseLocalContext<List<ClassificationResult>>{

	//有文件的话优先对文件分类
	//没有文件的话优先对批量文件分类
	//没有批量文件的话对一段文件进行分类.
	String fileToClassify;
	List<String> batchTextToClassify;
	String textToClassify;
	
	LibSVMHolderContext holder;
	List<ClassificationResult> result;
	
	String libsvmDir = ApplicationConfiguration.getInstance().getProperty("LIBSVM_DATA_DIR");
	/**
	 * @param lock
	 * @param inputDir
	 * @param outputDir
	 */
	public LibSVMClssifyExecuteContext(ReadWriteLock lock, String inputDir, String outputDir,LibSVMHolderContext ctx) {
		super(lock, inputDir, outputDir);
		this.holder = ctx;
	}

	String targetName = "sample_libsvm_data.txt";
	String outputName = "output.txt";

	Map<String,Object> resultMap = new TreeMap<String,Object>();
	
	@Override
	public Map<String, Object> getResultMapForRender() {
		// TODO Auto-generated method stub
		return resultMap;
	}


	@Override
	public void fireInternal() throws Exception{
		//把自然文本转化成向量..需要访问http
	
		result = new ArrayList<ClassificationResult>(10);
		
		this.lock.readLock().lock();
		try{
			if(fileToClassify!=null){
				try(BufferedReader br = new BufferedReader(new FileReader(new File(libsvmDir,fileToClassify)));){
					String line = "";
					while((line=br.readLine())!=null){
						result.add(dist2CR(holder, getUnlabeledLineDistribution(line)));
					}
					br.close();
				}
			}else if(batchTextToClassify!=null){
				for(String s : batchTextToClassify){
					result.add(dist2CR(holder, getUnlabeledLineDistribution(s)));
				}
			}else{
				
				Map<String,Object> m = new TreeMap<String,Object>();
				m.put("text",textToClassify);
				Word2VecDocTransContext wvdtc = ExecuteContextManager.getW2vbuilder().newDocTrans(m).parseText().build();
				wvdtc.fire();
				DocumentVectorMessage msg = (DocumentVectorMessage) wvdtc.getResultMapForRender().get(Constant.COMMAND_RESULT);
				result.add(dist2CR(holder, getUnlabeledLineDistribution(doubleArr2LibSVMVec(msg.getData()[0].getVector().getValues()))));
			}
			resultMap.put(Constant.COMMAND_RESULT, result);
		}finally{
			this.lock.readLock().unlock();
		}
		
	}
	private String doubleArr2LibSVMVec(double []arr){
		StringBuilder sb = new StringBuilder();
		for(int i = 0;i<arr.length;i++){
			sb.append(i);
			sb.append(":");
			sb.append(arr[i]);
			if(i<arr.length-1){
				sb.append(" ");
			}
		}
		return sb.toString();
	}
	private ClassificationResult dist2CR(LibSVMHolderContext holder,double [] dist){
		LibSVMClassificationResult cr = new LibSVMClassificationResult();
		cr.setDistribution(dist);
		cr.setLabel(holder.getModel().label);
		cr.setTrueLabel(-1);
		return cr;
	}
	
	private double [] getUnlabeledLineDistribution(String s){
		return holder.distribution(s);
	}
	private double [] getlabeledLineDistribution(String s){
		return holder.distributionLabeled(s);
	}
	public ClassificationResult getLabeledLineDistribution(String s){
		LibSVMClassificationResult cr = new LibSVMClassificationResult();
		double dist[] = getlabeledLineDistribution(s);
		cr.setDistribution(dist);
		cr.setLabel(holder.getModel().label);
		boolean isTab =  s.indexOf("\t")!=-1;
		int trueLabel = -1;
		if(isTab){
			trueLabel = Integer.parseInt(s.split("\t")[0]);
		}else{
			trueLabel = Integer.parseInt(s.split(" ")[0]);
		}
		cr.setTrueLabel(trueLabel);
		return cr;
	}


	/**
	 * @return the fileToClassify
	 */
	public String getFileToClassify() {
		return fileToClassify;
	}


	/**
	 * @param fileToClassify the fileToClassify to set
	 */
	public void setFileToClassify(String fileToClassify) {
		this.fileToClassify = fileToClassify;
	}


	/**
	 * @return the batchTextToClassify
	 */
	public List<String> getBatchTextToClassify() {
		return batchTextToClassify;
	}


	/**
	 * @param batchTextToClassify the batchTextToClassify to set
	 */
	public void setBatchTextToClassify(List<String> batchTextToClassify) {
		this.batchTextToClassify = batchTextToClassify;
	}


	/**
	 * @return the textToClassify
	 */
	public String getTextToClassify() {
		return textToClassify;
	}


	/**
	 * @param textToClassify the textToClassify to set
	 */
	public void setTextToClassify(String textToClassify) {
		this.textToClassify = textToClassify;
	}

	@Override
	public List<ClassificationResult> javaClassResult() {
		return result;
	}

}
